/**
 * eCommerce Application Sample for J2EE Training
 * @author Fabienne Boyer - july 2000
 * @author Didier Donsez - november 2002
 */
package miagetest.client.shell;

import miagetest.client.interfaces.ShellCommand;
import miagetest.client.interfaces.ShellContext;
import miagetest.client.interfaces.ShellConstantes;
import java.io.*;
import java.util.TreeMap;
import java.io.PrintStream;

public abstract class ShellAbstract implements Runnable, ShellConstantes {
    // Chargement des commandes pour le contexte

    private TreeMap _commandNameMap = new TreeMap();
    private ShellContext _context = new ShellContextImpl(_commandNameMap);
    private boolean stop = false;
    protected String serverName; //args[0]
    // Variables de flux
    protected InputStream in; //args[1]
    protected PrintStream out;
    protected PrintStream err;

    protected boolean parseArgs(String args[]) {
        if (args.length == 0) //no args
        {
            in = System.in;
            serverName = "localhost";
            return true;
        }
    
        if (args.length == 1) //only serverName arg
        {
            in = System.in;
            serverName = args[0];
            return true;
        } else {
            try {
                serverName = args[0];
                in = new FileInputStream(args[1]);
                return true;
            } catch (java.io.FileNotFoundException f) {
                err.println("File \"" + args[1] + "\"not found");
                return false;
            }

        }
    }

    protected final ShellContext getContext() {
        return _context;
    }

    protected final void stop() {
        stop = true;
    }

    public final void run() {
        String banner;
        String line;
        BufferedReader br = null;

        // Affichage de la bani�re
        if (!stop) {
            banner = (String) _context.getVar(BANNER);
            if (banner != null) {
                out.println(banner);
            }
            line = null;
            br = new BufferedReader(new InputStreamReader(in));
        }

        while (!stop) {
            //Affichage invite de commande
            String prompt;
            prompt = (String) _context.getVar(PROMPT);
            if (prompt == null) {
                prompt = ">";
            }
            out.print(prompt);

            // Lecture de la commande du client
            try {
                line = br.readLine();
            } catch (IOException ex) {
                err.println("Could not read input, please try again.");
                continue;
            }


            line = line.trim();

            if (line.length() == 0) {
                continue;
            }

            // Execution de la commande si conforme
            try {
                executeCommand(line, out, err);
            } catch (Exception ex) {
                err.println("Shell: " + ex);
            }
        }
    }

    public abstract String getBanner();

    protected final synchronized void removeCommand(String name) {
        out.println("Removing command  : " + name);
        _commandNameMap.remove(name);
    }

    // ! Execution de la commande r�cup�r�e !
    protected final synchronized void executeCommand(
            String commandLine, PrintStream out, PrintStream err) throws Exception {
        commandLine = commandLine.trim();

        //Extraction de la commande sans les arguments
        String commandName = (commandLine.indexOf(' ') >= 0)
                ? commandLine.substring(0, commandLine.indexOf(' ')) : commandLine;

        // R�cup�ration de la commande avec la Map
        ShellCommand command = getCommand(commandName);
        if (command != null) {
            // Execution de la m�thode "execute" de la ShellCommand d�termin�e
            command.execute(commandLine, out, err);
        } else {
            err.println("Command not found.");
        }
    }

    // Retourne la ShellCommand associ�e au nom rentr� en param�tre
    protected final synchronized ShellCommand getCommand(String name) {
        ShellCommand sc = (ShellCommand) _commandNameMap.get(name);
        return sc;
    }

    // Ajoute des commandes disponibles
    protected final synchronized void addCommand(ShellCommand sc) {
        _commandNameMap.put(sc.getName(), sc);
    }

    // Vide la liste des commandes disponibles
    protected final synchronized void clearCommands() {
        _commandNameMap.clear();
    }
}
